home *** CD-ROM | disk | FTP | other *** search
/ Aminet 3 / Aminet 3 - July 1994.iso / Aminet / misc / emu / SpecConvert106.lha / src / spconv.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-18  |  34.2 KB  |  1,847 lines

  1. #include <stdio.h>
  2.  
  3. #if defined(__STDC__) || defined(__TURBOC__)
  4. #include <stdlib.h>
  5. #else
  6. #include <sys/types.h>
  7. #endif
  8.  
  9. #ifdef __TURBOC__
  10. #include <io.h>
  11. #endif
  12.  
  13. #include <stdio.h>
  14. #include <fcntl.h>
  15. #include <sys/stat.h>
  16. #include <string.h>
  17. #ifdef __TURBOC__
  18. #include <alloc.h>
  19. #else
  20. #include <stdlib.h>
  21. #endif
  22.  
  23. #ifndef O_BINARY
  24. #define O_BINARY 0
  25. #endif
  26.  
  27. #include "spconv.h"
  28.  
  29. struct sna_s sna;
  30. struct vga_s vga;
  31. struct z80_s z80;
  32. struct prg_s prg;
  33. struct ach_s ach;
  34. struct kgb_s kgb;
  35.  
  36. /* extra space just in case the Z80 uncompress fails due to a corrupt image */
  37. unsigned char image[IMSIZE+0x100]; 
  38. unsigned int z80_size;
  39.  
  40. int    intype;
  41. int    outtype;
  42.  
  43. /* Path names are limited to 80 characters under MSDOS so this sould be */
  44. /* enough... If you are using UNIX than you may have to make this array */
  45. /* larger.                                                              */
  46. char    my_directory[120];
  47.  
  48. /* this fd is used all over the place, defined only once here */
  49. FILE * fd;
  50.  
  51. int main(int argc,char *argv[])
  52. {
  53.     char *p;
  54.     struct stat status;
  55.     char * fromstring;
  56.     char * tostring;
  57.     char * outfile;
  58.  
  59. #ifdef __TURBOC__
  60.     /* for Trubo-C: open all files in binary mode */
  61.     extern int _fmode;
  62.     _fmode = O_BINARY;
  63. #endif
  64.  
  65.     if(argc != 3) {
  66.         fprintf(stderr,"SPCONV version 1.06 - %s\n\n",__DATE__);
  67.         fprintf(stderr,"Usage: spconv <source> <target>\n\n");
  68.         fprintf(stderr,"Source must be a valid .SNA(PSHOT), .SP, .Z80, .PRG, .ACH, .ZX or RAW file.\n");
  69.         fprintf(stderr,"Target must be a .SNA(PSHOT), .SP, .Z80, .PRG, .ACH or .ZX file.\n\n");
  70.         fprintf(stderr,"If the second parameter contains only a suffix, the prefix\n");
  71.         fprintf(stderr,"of the input file will be used (i.e. 'spconv file.sna .z80')\n\n");
  72.         fprintf(stderr,"Output .SP files are in the new format, .Z80 files are compressed\n");
  73.         fprintf(stderr,"in the version 1.45 .Z80 format\n\n");
  74.         fprintf(stderr,"If <source> and <target> are .SP files, convertion from old\n");
  75.         fprintf(stderr,"to new format or from new to old format will be performed.\n");
  76.         fprintf(stderr,"If <source> and <target> are .Z80 files, convertion to\n");
  77.         fprintf(stderr,"the version 1.45 format will be performed.\n");
  78.         fprintf(stderr,"If <source> and <target> are of the same type an error message\n");
  79.         fprintf(stderr,"will be generated (unless they are both .SP or .Z80 files)\n");
  80.         fprintf(stderr,"\n\nPublic Domain, H. de Groot 1993 (Amiga conversion: Kjell Irgens)\n\n");
  81.  
  82.         return 1;
  83.     }
  84.  
  85.     if((strchr(argv[1],'*')!=NULL) || (strrchr(argv[1],'?')!=NULL) ||
  86.        (strchr(argv[2],'*')!=NULL) || (strrchr(argv[2],'?')!=NULL))    {
  87.         fprintf(stderr,"This program can't handle wildcards, sorry!\n");
  88.         return 1;
  89.     }
  90.  
  91.     strcpy(my_directory,argv[0]);
  92.     if(strrchr(my_directory,'\\')!=NULL) {
  93.         *strrchr(my_directory,'\\')='\0';
  94.     }
  95.     else if(strrchr(my_directory,'/')!=NULL) {
  96.         *strrchr(my_directory,'/')='\0';
  97.     }
  98.     else if(strrchr(my_directory,':')!=NULL) {
  99.         *strrchr(my_directory,':')='\0';
  100.     } else {
  101.         my_directory[0]='\\';
  102.         my_directory[1]='\0';
  103.     }
  104.  
  105.     if(stat(argv[1],&status)<0) {
  106.         perror(argv[1]);
  107.         return 1;
  108.     }
  109.  
  110.     /* 
  111.      * recognize input type on filename:
  112.      *
  113.      *    .SNA    ->    SNA file (used in JPP)
  114.      *    .SP    ->    SP file (was VGASPEC)
  115.      *    .Z80    ->    Z80 file
  116.      *    .PRG    ->    PRG file
  117.      *    .ACH    ->    ACH file (from archimedes emulator)
  118.      *    .ZX    ->    KGB file (from KGB emulator)
  119.      *    other    ->    if exact 48+header -> raw file
  120.      *    otherwise     unknown
  121.      */
  122.  
  123.     intype=UNKNOWN;
  124.     p=strrchr(argv[1],'.');
  125.     if(p==NULL) p=argv[1]; /* not found, set at begin of string */
  126.     if((strcmp(p,".SNA")==0) || (strcmp(p,".sna")==0)) {
  127.         fromstring=".SNA";
  128.         intype=SNA;
  129.     }
  130.     else if(strcmp(p,".snapshot")==0 || strcmp(p,".SNAPSHOT")==0) {
  131.         fromstring=".snapshot";
  132.         intype=SNA;
  133.     }
  134.     if((strcmp(p,".Z80")==0) || (strcmp(p,".z80")==0)) {
  135.         fromstring=".Z80";
  136.         intype=Z80;
  137.     }
  138.     if((strcmp(p,".SP")==0) || (strcmp(p,".sp")==0)) {
  139.         fromstring=".SP";
  140.         intype=SP;
  141.     }
  142.     if((strcmp(p,".PRG")==0) || (strcmp(p,".prg")==0)) {
  143.         fromstring=".PRG";
  144.         intype=PRG;
  145.     }
  146.     if((strcmp(p,".ACH")==0) || (strcmp(p,".ach")==0)) {
  147.         fromstring=".ACH";
  148.         intype=ACH;
  149.     }
  150.     if((strcmp(p,".ZX")==0) || (strcmp(p,".zx")==0)) {
  151.         fromstring=".ZX";
  152.         intype=KGB;
  153.     }
  154.  
  155.     if(intype==UNKNOWN)
  156.         if (status.st_size == (sizeof(h)+IMSIZE)) {
  157.             fromstring="RAW";
  158.             intype=RAW;
  159.         }
  160.  
  161.     /* 
  162.      * recognize output type on filename:
  163.      *
  164.      *    .SNA    ->    SNA file
  165.      *    .SP    ->    SP file (was VGASPEC)
  166.      *    .Z80    ->    Z80 file
  167.      *    .PRG    ->    PRG file
  168.      *    .ACH    ->    ACH file (from archimedes emulator)
  169.      *    .ZX    ->    KGB file (from KGB emulator)
  170.      *    otherwise     unknown
  171.      */
  172.     outtype=UNKNOWN;
  173.  
  174.     p=strrchr(argv[2],'.');
  175.     if(p==NULL) p=argv[2]; /* not found, set at begin of string */
  176.     if((strcmp(p,".SNA")==0) || (strcmp(p,".sna")==0)) {
  177.         tostring=".SNA";
  178.         outtype=SNA;
  179.     }
  180.     else if(strcmp(p,".snapshot")==0 || strcmp(p,".SNAPSHOT")==0) {
  181.         tostring=".snapshot";
  182.         outtype=SNA;
  183.     }
  184.     if((strcmp(p,".Z80")==0) || (strcmp(p,".z80")==0)) {
  185.         tostring=".Z80";
  186.         outtype=Z80;
  187.     }
  188.     if((strcmp(p,".SP")==0) || (strcmp(p,".sp")==0)) {
  189.         tostring=".SP";
  190.         outtype=SP;
  191.     }
  192.     if((strcmp(p,".PRG")==0) || (strcmp(p,".prg")==0)) {
  193.         tostring=".PRG";
  194.         outtype=PRG;
  195.     }
  196.     if((strcmp(p,".ACH")==0) || (strcmp(p,".ach")==0)) {
  197.         tostring=".ACH";
  198.         outtype=ACH;
  199.     }
  200.     if((strcmp(p,".ZX")==0) || (strcmp(p,".zx")==0)) {
  201.         tostring=".ZX";
  202.         outtype=KGB;
  203.     }
  204.  
  205.     if(intype==UNKNOWN) {
  206.         fprintf(stderr,"Unknown input file format. Must be a valid .SNA, .SP, .Z80, .PRG, .ACH or\n");
  207.         fprintf(stderr,".ZX file, or a Raw file\n");
  208.         return 3;
  209.     }
  210.  
  211.     if(outtype==UNKNOWN) {
  212.         fprintf(stderr,"Unknown output file format. Must be a .SNA, .SP, .Z80, .PRG, .ACH or .ZX file\n");
  213.         return 4;
  214.     }
  215.  
  216.     /* 
  217.        if argv[2] only contains the suffix then use the prefix of
  218.        argv[1];
  219.      */
  220.     if(argv[2][0]=='.') {
  221.         outfile=malloc(strlen(argv[1])+strlen(argv[2])+1);
  222.         strcpy(outfile,argv[1]); /* copy prefix    */
  223.  
  224.         p=strrchr(outfile,'.');
  225.         if(p!=NULL) *p='\0'; /* put end of string at position of '.' */
  226.  
  227.         strcat(outfile,argv[2]); /* append suffix  */
  228.     } else {
  229.         outfile=malloc(strlen(argv[2])+1);
  230.  
  231.         strcpy(outfile,argv[2]);
  232.     }
  233.  
  234.     /*
  235.      * Special conversion between versions of the same type.
  236.      * This currently only applies to .SP and the .Z80 formats.
  237.      *
  238.      * The .SP formats will convert from the New to the Old format or
  239.      * from the Old to the New format, controled by the current format
  240.      * of the input.
  241.      *
  242.      * The .Z80 formats will convert to the version 1.45 .Z80 format
  243.      * since version 1.45 .Z80 files can be read by both old and new
  244.      * Z80-emulators.
  245.      */
  246.  
  247.     if(intype==outtype)
  248.     {
  249.         if((intype!=SP) && (intype!=Z80)) {
  250.         fprintf(stderr,"Input and output file format are the same. ");
  251.         fprintf(stderr,"What you try to do\n");
  252.         fprintf(stderr,"is handled much better by the MSDOS \"COPY\" ");
  253.         fprintf(stderr,"command!\n");
  254.         return 3;
  255.         } else if(intype==SP) {
  256.             if((status.st_size == (sizeof(vga)+IMSIZE))) {
  257.                 printf("Converting %s from new .SP format to old .SP format.\n",argv[1]);
  258.                 read_vgaspec(argv[1]);
  259.  
  260.                 write_old_vgaspec(outfile);
  261.                 return 0;
  262.             }
  263.             else if((status.st_size == (sizeof(vga)+IMSIZE-6))) {
  264.                 read_vgaspec_header(argv[1]);
  265.                 if((vga.S=='S')&&(vga.P=='P')) {
  266. fprintf(stderr,"Invalid input file format. This could be a new syle .SP file with\n");
  267. fprintf(stderr,"an image of another length than 48Kb. This kind of .SP files cannot\n");
  268. fprintf(stderr,"be converted. All other file formats (including the old .SP format)\n");
  269. fprintf(stderr,"contain images of 48Kb length.\n");
  270.                     return 3;
  271.                 }
  272.  
  273.                 printf("Converting %s from old .SP format to new .SP format.\n",argv[1]);
  274.                 read_old_vgaspec(argv[1]);
  275.                 vga.S='S';
  276.                 vga.P='P';
  277.                 vga.len_l=0x00;
  278.                 vga.len_h=0xC0;
  279.                 vga.start_l=0x00;
  280.                 vga.start_h=0x40;
  281.                 write_vgaspec(outfile);
  282.                 return 0;
  283.             } else {
  284.                 read_vgaspec_header(argv[1]);
  285.                 if((vga.S=='S')&&(vga.P=='P')) {
  286. fprintf(stderr,"Invalid input file format. This could be a new syle .SP file with\n");
  287. fprintf(stderr,"an image of another length than 48Kb. This kind of .SP files cannot\n");
  288. fprintf(stderr,"be converted. All other file formats (including the old .SP format)\n");
  289. fprintf(stderr,"contain images of 48Kb length.\n");
  290.                     return 3;
  291.                 } else {
  292. fprintf(stderr,"Unknown input file format. Must be a valid .SNA, .SP, .Z80, .PRG, .ACH, .ZX or RAW file\n");
  293.                     return 3;
  294.                 }
  295.             }
  296.         } else {
  297.             printf("Converting %s from %s to %s (output in version 1.45 format)\n",argv[1],fromstring,tostring);
  298.             read_z80(argv[1]);
  299.  
  300.             write_z80(outfile);
  301.             return 0;
  302.         }
  303.     }
  304.  
  305.     /*
  306.      * General conversion from one type to another
  307.      */
  308.  
  309.     printf("Converting %s from %s to %s\n",argv[1],fromstring,tostring);
  310.  
  311.     /*
  312.      * convert input_file to SNA
  313.      */
  314.  
  315.     switch(intype) {
  316.     case SNA:    if (status.st_size == (sizeof(sna)+IMSIZE)) {
  317.                 read_sna(argv[1]);
  318.             }
  319.             break;
  320.     case SP:    if ((status.st_size == (sizeof(vga)+IMSIZE))) {
  321.                 read_vgaspec(argv[1]);
  322.                 vgaspec_to_sna();
  323.             } else if ((status.st_size == (sizeof(vga)+IMSIZE-6))) {
  324.                 read_old_vgaspec(argv[1]);
  325.                 vgaspec_to_sna();
  326.             }
  327.             break;
  328.     case RAW:    read_raw(argv[1]);
  329.             raw_to_sna();
  330.             break;
  331.     case Z80:    read_z80(argv[1]);
  332.             z80_to_sna();
  333.             break;
  334.     case PRG:    if(status.st_size != (sizeof(prg)+IMSIZE)) {
  335.                 printf("Warning: the image part of %s is not exactly 48k!\n",argv[1]);
  336.                 printf("         Converting anyway, the converted file may not work\n");
  337.             }
  338.             read_prg(argv[1]);
  339.             prg_to_sna();
  340.             break;
  341.     case ACH:    if(status.st_size == (sizeof(ach)+16384L+IMSIZE)) {
  342.                 read_ach(argv[1]);
  343.                 ach_to_sna();
  344.             }
  345.             break;
  346.     case KGB:    if(status.st_size == (132L+IMSIZE+sizeof(kgb))) {
  347.                 read_kgb(argv[1]);
  348.                 kgb_to_sna();
  349.             }
  350.             break;
  351.     default:    printf("Unrecognized input file type, can't convert\n");
  352.             return 3;
  353.     }
  354.  
  355.     /*
  356.      * convert internal SNA format to output file
  357.      */
  358.  
  359.     switch(outtype) {
  360.     case SNA:    write_sna(outfile);
  361.             break;
  362.     case SP:    sna_to_vgaspec();
  363.             write_vgaspec(outfile);
  364.             break;
  365.     case Z80:    sna_to_z80();
  366.             write_z80(outfile);
  367.             break;
  368.     case PRG:    sna_to_prg(outfile);
  369.             write_prg(outfile);
  370.             break;
  371.     case ACH:    sna_to_ach();
  372.             write_ach(outfile);
  373.             break;
  374.     case KGB:    sna_to_kgb();
  375.             write_kgb(outfile);
  376.             break;
  377.     default:    printf("Unrecognized output file type, can't convert\n");
  378.             return 4;
  379.     }
  380.  
  381.     /*
  382.      * That's it, simple isn't it?
  383.      */
  384.     return 0;
  385. }
  386.  
  387. /* I/O FUNCTIONS */
  388.  
  389. /* GENERIC I/O - READ/WRITE RAM IMAGE */
  390.  
  391. void read_image(char * s)
  392. {
  393.     if(fread(image, (size_t) IMSIZE, 1, fd)!=1) {
  394.         perror(s);
  395.         exit(1);
  396.     }
  397. }
  398.  
  399. void write_image(char * s)
  400. {
  401.     if(fwrite(image, (size_t) IMSIZE, 1, fd)!=1) {
  402.         perror(s);
  403.         exit(2);
  404.     }
  405. }
  406.  
  407. /* SPECIFIC I/O - READ/WRITE .SNA IMAGE */
  408.  
  409. void read_sna(char * s)
  410. {
  411.     fd=fopen(s,"r");
  412.     if(fd == NULL) {
  413.         perror(s);
  414.         exit(1);
  415.     }
  416.     if(fread(&sna, sizeof(sna), 1, fd)!=1) {
  417.         perror(s);
  418.         exit(1);
  419.     }
  420.     read_image(s);
  421.     fclose(fd);
  422. }
  423.  
  424. void write_sna(char * s)
  425. {
  426.     unlink(s);
  427.  
  428.     fd=fopen(s,"w");
  429.     if(fd == NULL) {
  430.         perror(s);
  431.         exit(2);
  432.     }
  433.         
  434.     if(fwrite(&sna,(size_t) sizeof(sna),1,fd)!=1) {
  435.         perror(s);
  436.         exit(2);
  437.     }
  438.     write_image(s);
  439.     fclose(fd);
  440. }
  441.  
  442. /* SPECIFIC I/O - READ NEW .SP HEADER */
  443.  
  444. void read_vgaspec_header(char * s)
  445. {
  446.     fd=fopen(s,"r");
  447.     if(fd == NULL) {
  448.         perror(s);
  449.         exit(1);
  450.     }
  451.     if(fread(&vga,sizeof(vga),1,fd)!=1) {
  452.         perror(s);
  453.         exit(1);
  454.     }
  455.     fclose(fd);
  456. }
  457.  
  458. /* SPECIFIC I/O - READ/WRITE NEW .SP IMAGE */
  459.  
  460. void read_vgaspec(char * s)
  461. {
  462.     fd=fopen(s,"r");
  463.     if(fd == NULL) {
  464.         perror(s);
  465.         exit(1);
  466.     }
  467.     if(fread(&vga,sizeof(vga),1,fd)!=1) {
  468.         perror(s);
  469.         exit(1);
  470.     }
  471.     read_image(s);
  472.     fclose(fd);
  473. }
  474.  
  475. void write_vgaspec(char * s)
  476. {
  477.     unlink(s);
  478.  
  479.     fd=fopen(s,"w");
  480.     if(fd == NULL) {
  481.         perror(s);
  482.         exit(2);
  483.     }
  484.  
  485.     if(fwrite(&vga,sizeof(vga),1,fd)!=1) {
  486.         perror(s);
  487.         exit(2);
  488.     }
  489.     write_image(s);
  490.     fclose(fd);
  491. }
  492.  
  493. /* SPECIFIC I/O - READ/WRITE OLD .SP IMAGE */
  494.  
  495. void read_old_vgaspec(char * s)
  496. {
  497.     fd=fopen(s,"r");
  498.     if(fd == NULL) {
  499.         perror(s);
  500.         exit(1);
  501.     }
  502.     if(fread((void *)(((char *)&vga)+6),sizeof(vga)-6,1,fd)!=1) {
  503.         perror(s);
  504.         exit(1);
  505.     }
  506.     read_image(s);
  507.     fclose(fd);
  508. }
  509.  
  510. void write_old_vgaspec(char * s)
  511. {
  512.     unlink(s);
  513.  
  514.     fd=fopen(s,"w");
  515.     if(fd == NULL) {
  516.         perror(s);
  517.         exit(2);
  518.     }
  519.  
  520.     if(fwrite((void *)(((char *)&vga)+6),sizeof(vga)-6,1,fd)!=1) {
  521.         perror(s);
  522.         exit(2);
  523.     }
  524.     write_image(s);
  525.     fclose(fd);
  526. }
  527.  
  528. /* SPECIFIC I/O - READ RAW IMAGE */
  529.  
  530. void read_raw(char * s)
  531. {
  532.     int i;
  533.  
  534.     fd=fopen(s,"r");
  535.     if(fd == NULL) {
  536.         perror(s);
  537.         exit(1);
  538.     }
  539.     if(fread(&h,sizeof(h),1,fd)!=1) {
  540.         perror(s);
  541.         exit(1);
  542.     }
  543.     for(i=0;i<9;i++) {
  544.         if(h.in[i]!=expect[i]) {
  545.             fprintf(stderr,"Header of spectum image not ok, ");
  546.             fprintf(stderr,"Spectrum image should be saved with:\n");
  547.             fprintf(stderr,"SAVE *\"b\"CODE 16384,49152");
  548.             exit(1);
  549.         }
  550.     }
  551.     read_image(s);
  552.     fclose(fd);
  553. }
  554.  
  555. /* SPECIFIC I/O - READ/WRITE .Z80 IMAGE */
  556.  
  557. void read_z80(char * s)
  558. {
  559.     fd=fopen(s,"r");
  560.     if(fd == NULL) {
  561.         perror(s);
  562.         exit(1);
  563.     }
  564.     /* read old header part */
  565.     if(fread(&z80,z80_145_size,1,fd)!=1) {
  566.         perror(s);
  567.         exit(1);
  568.     }
  569.     /* check for 2.01 format */
  570.     if((z80.pch == (unsigned char) 0) &&
  571.        (z80.pcl == (unsigned char) 0)) {
  572.  
  573.         /* 2.01 or better format, check if we can use this */
  574.         unsigned char *p;
  575.         p = (unsigned char *) &z80;
  576.  
  577.         /* read an aditional 2 bytes */
  578.         if(fread(&p[z80_145_size],2,1,fd)!=1) {
  579.             perror(s);
  580.             exit(1);
  581.         }
  582.         if((p[z80_145_size] != (unsigned char) 23) &&
  583.            (p[z80_145_size+1] != (unsigned char) 0)) {
  584.             fprintf(stderr,"%s seems to be a new type Z80 file!\n",s);
  585.             fprintf(stderr,"This program can only read files up to version 2.01 format\n");
  586.             exit(1);
  587.         }
  588.         /* we passed this test, read the 23 byte long extra header */
  589.         if(fread(&p[z80_145_size+2],23,1,fd)!=1) {
  590.             perror(s);
  591.             exit(1);
  592.         }
  593.         /* we got a complete header now. */
  594.         /* check the type of the file... */
  595.         if((unsigned int) z80.hardware >= 3) {
  596.             fprintf(stderr,"%s is not a 48K Spectrum Z80 file, can't convert!\n",s);
  597.             exit(1);
  598.         }
  599.         /* check if the interface-1 rom was paged in */
  600.         if(z80.if1_paged != (unsigned char) 0) {
  601.             fprintf(stderr,"%s has interface-1 rom paged in, can't convert!\n",s);
  602.             exit(1);
  603.         }
  604.         /* all fine up till now, put PC back to the old place and reset the */
  605.         /* compressed memory bit, the z80_read_page function uncompresses.  */
  606.         z80.pch = z80.n_pch;
  607.         z80.pcl = z80.n_pcl;
  608.         z80.data = z80.data & ~0x20; /* reset compressed mode bit to be sure */
  609.  
  610.         while(z80_read_page(s)!=0);
  611.     } else {
  612.         /* The file is in version 1.45 format.             */
  613.         /* Read and decompress if the image is compressed, */
  614.         /* just read if it is not compressed at all...     */
  615.  
  616.         if((z80.data & 0x20)!=0) {
  617.             z80_read_uncompress(fd,0,(unsigned int) IMSIZE);
  618.             z80.data = z80.data & ~0x20; /* reset compressed mode bit to be sure */
  619.         } else {
  620.             read_image(s);
  621.         }
  622.     }
  623.     fclose(fd);
  624. }
  625.  
  626. void write_z80(char * s)
  627. {
  628.     unlink(s);
  629.  
  630.     fd=fopen(s,"w");
  631.     if(fd == NULL) {
  632.         perror(s);
  633.         exit(2);
  634.     }
  635.  
  636.     /* Try to compress the data */
  637.     z80.data=z80.data | z80_compress();
  638.  
  639.     if(fwrite(&z80,z80_145_size,1,fd)!=1) {
  640.         perror(s);
  641.         exit(2);
  642.     }
  643.     if(fwrite(image,z80_size,1,fd)!=1) {
  644.         perror(s);
  645.         exit(2);
  646.     }
  647.     fclose(fd);
  648. }
  649.  
  650. /* SPECIFIC I/O - READ/WRITE .PRG IMAGE */
  651.  
  652. void read_prg(char * s)
  653. {
  654.     fd=fopen(s,"r");
  655.     if(fd == NULL) {
  656.         perror(s);
  657.         exit(1);
  658.     }
  659.     if(fread(&prg,sizeof(prg),1,fd)!=1) {
  660.         perror(s);
  661.         exit(1);
  662.     }
  663.     read_image(s);
  664.     fclose(fd);
  665. }
  666.  
  667. void write_prg(char * s)
  668. {
  669.     unlink(s);
  670.  
  671.     fd=fopen(s,"w");
  672.     if(fd == NULL) {
  673.         perror(s);
  674.         exit(2);
  675.     }
  676.  
  677.     if(fwrite(&prg,sizeof(prg),1,fd)!=1) {
  678.         perror(s);
  679.         exit(2);
  680.     }
  681.     write_image(s);
  682.     fclose(fd);
  683. }
  684.  
  685. /* SPECIFIC I/O - READ/WRITE .ACH IMAGE */
  686.  
  687. void read_ach(char * s)
  688. {
  689.     fd=fopen(s,"r");
  690.     if(fd == NULL) {
  691.         perror(s);
  692.         exit(1);
  693.     }
  694.     if(fread(&ach,sizeof(ach),1,fd)!=1) {
  695.         perror(s);
  696.         exit(1);
  697.     }
  698.     /* fseek over the 16K ram area */
  699.     if(fseek(fd,16384L,SEEK_CUR)!=0) {
  700.         perror(s);
  701.         exit(1);
  702.     }
  703.     read_image(s);
  704.     fclose(fd);
  705. }
  706.  
  707. void write_ach(char * s)
  708. {
  709.     char buffer[1024];
  710.     char *p;
  711.     int  i;
  712.     struct stat status;
  713.     char * rom;
  714.  
  715.     /* clean buffer first */
  716.     p=(char *) buffer;
  717.     for(i=0; i < 1024; i++) p[i]='\0';
  718.  
  719.     unlink(s);
  720.  
  721.     fd=fopen(s,"w");
  722.     if(fd == NULL) {
  723.         perror(s);
  724.         exit(2);
  725.     }
  726.  
  727.     if(fwrite(&ach,sizeof(ach),1,fd)!=1) {
  728.         perror(s);
  729.         exit(2);
  730.     }
  731.  
  732.     strcat(my_directory,"\\spectrum.rom");
  733.  
  734.     rom=NULL;
  735.  
  736.     if(stat("spectrum.rom",&status)>=0) {
  737.         rom="spectrum.rom";
  738.     }
  739.     else if (stat(my_directory,&status)>=0)    {
  740.         rom=my_directory;
  741.     }
  742.  
  743.     if(rom==NULL) {
  744.         printf("Warning: The file \"spectrum.rom\" needed for proper conversion to the .ach\n");
  745.         printf("         format could not be located, Converting anyway. The ROM space\n");
  746.         printf("         will be filled with 0 bytes, the converted file may not work\n");
  747.  
  748.         /* write the 16K ram area as zero's */
  749.         for(i=0; i < 16; i++) {
  750.             if(fwrite(buffer,1024,1,fd)!=1) {
  751.                 perror(s);
  752.                 exit(2);
  753.             }
  754.         }
  755.     } else {
  756.         FILE *  fd_specrom;
  757.  
  758.         if (status.st_size != 16384) {
  759.         printf("Warning: The file \"spectrum.rom\" needed for proper conversion to the .ach\n");
  760.         printf("         format has a wrong size (not 16K). Converting anyway. The ROM space\n");
  761.         printf("         will be filled with 0 bytes, the converted file may not work\n");
  762.  
  763.             /* copy the 16K ROM area */
  764.             for(i=0; i < 16; i++) {
  765.                 if(fwrite(buffer,1024,1,fd)!=1) {
  766.                     perror(s);
  767.                     exit(2);
  768.                 }
  769.             }
  770.         } else {
  771.             printf("Using Spectrum ROM: %s\n",rom);
  772.  
  773.             fd_specrom=fopen(rom,"r");
  774.             if(fd_specrom==NULL) {
  775.                 perror(rom);
  776.                 exit(2);
  777.             }
  778.  
  779.             for(i=0; i < 16; i++) {
  780.                 if(fread(buffer,1024,1,fd_specrom)!=1) {
  781.                     perror(rom);
  782.                     exit(2);
  783.                 }
  784.                 if(fwrite(buffer,1024,1,fd)!=1) {
  785.                     perror(s);
  786.                     exit(2);
  787.                 }
  788.             }
  789.             fclose(fd_specrom);
  790.         }
  791.     }
  792.     write_image(s);
  793.     fclose(fd);
  794. }
  795.  
  796. /* SPECIFIC I/O - READ/WRITE .ZX IMAGE */
  797.  
  798. void read_kgb(char * s)
  799. {
  800.     fd=fopen(s,"r");
  801.     if(fd == NULL) {
  802.         perror(s);
  803.         exit(1);
  804.     }
  805.  
  806.     /* fseek over the first 132 bytes */
  807.     if(fseek(fd,132L,SEEK_CUR)!=0) {
  808.         perror(s);
  809.         exit(1);
  810.     }
  811.  
  812.     read_image(s);
  813.  
  814.     if(fread(&kgb,sizeof(kgb),1,fd)!=1) {
  815.         perror(s);
  816.         exit(1);
  817.     }
  818.  
  819.     fclose(fd);
  820. }
  821.  
  822. void write_kgb(char * s)
  823. {
  824.     char buffer[132];
  825.     char *p;
  826.     int  i;
  827.     struct stat status;
  828.     char * rom;
  829.  
  830.     /* clean buffer first */
  831.     p=(char *) buffer;
  832.     for(i=0; i < 132; i++) p[i]='\0';
  833.  
  834.     unlink(s);
  835.  
  836.     fd=fopen(s,"w");
  837.     if(fd == NULL) {
  838.         perror(s);
  839.         exit(2);
  840.     }
  841.  
  842.     strcat(my_directory,"\\spectrum.rom");
  843.  
  844.     rom=NULL;
  845.  
  846.     if(stat("spectrum.rom",&status)>=0) {
  847.         rom="spectrum.rom";
  848.     }
  849.     else if (stat(my_directory,&status)>=0) {
  850.         rom=my_directory;
  851.     }
  852.  
  853.     if(rom==NULL) {
  854.         printf("Warning: The file \"spectrum.rom\" needed for proper conversion to the .zx\n");
  855.         printf("         format could not be located, Converting anyway. The 132 bytes needed\n");
  856.         printf("         from the ROM will be filled with 0 bytes, the converted file may not\n");
  857.         printf("         work\n");
  858.  
  859.         /* write the 132 byte area as zero's */
  860.         if(fwrite(buffer,132,1,fd)!=1) {
  861.             perror(s);
  862.             exit(2);
  863.         }
  864.     } else {
  865.         FILE *  fd_specrom;
  866.  
  867.         if (status.st_size != 16384) {
  868.         printf("Warning: The file \"spectrum.rom\" needed for proper conversion to the .zx\n");
  869.         printf("         format has a wrong size (not 16K). Converting anyway. The 132 bytes\n");
  870.         printf("         needed from the ROM will be filled with 0 bytes, the converted file\n");
  871.         printf("         may not work\n");
  872.  
  873.             /* write the 132 byte area as zero's */
  874.             if(fwrite(buffer,132,1,fd)!=1) {
  875.                 perror(s);
  876.                 exit(2);
  877.             }
  878.         } else {
  879.             printf("Using Spectrum ROM: %s\n",rom);
  880.  
  881.             fd_specrom=fopen(rom,"r");
  882.  
  883.             if(fd_specrom == NULL) {
  884.                 perror(rom);
  885.                 exit(2);
  886.             }
  887.  
  888.             /* fseek over the first 16384-132 bytes */
  889.             if(fseek(fd_specrom,16252L,SEEK_CUR)!=0) {
  890.                 perror(rom);
  891.                 exit(2);
  892.             }
  893.             if(fread(buffer,132,1,fd_specrom)!=1) {
  894.                 perror(rom);
  895.                 exit(2);
  896.             }
  897.             if(fwrite(buffer,132,1,fd)!=1) {
  898.                 perror(s);
  899.                 exit(2);
  900.             }
  901.             fclose(fd_specrom);
  902.         }
  903.     }
  904.  
  905.     write_image(s);
  906.     if(fwrite(&kgb,sizeof(kgb),1,fd)!=1) {
  907.         perror(s);
  908.         exit(2);
  909.     }
  910.  
  911.     fclose(fd);
  912. }
  913.  
  914. /* CONVERSION FUNCTIONS - TO .SNA FORMAT */
  915.  
  916. void vgaspec_to_sna()
  917. {
  918.     unsigned int addr;
  919.     unsigned int sp;
  920.  
  921.     sna.f=vga.f;
  922.     sna.a=vga.a;
  923.     sna.b=vga.b;
  924.     sna.c=vga.c;
  925.     sna.d=vga.d;
  926.     sna.e=vga.e;
  927.     sna.h=vga.h;
  928.     sna.l=vga.l;
  929.  
  930.     sna.fax=vga.fax;
  931.     sna.aax=vga.aax;
  932.     sna.bax=vga.bax;
  933.     sna.cax=vga.cax;
  934.     sna.dax=vga.dax;
  935.     sna.eax=vga.eax;
  936.     sna.hax=vga.hax;
  937.     sna.lax=vga.lax;
  938.  
  939.     sna.ixh=vga.ixh;
  940.     sna.ixl=vga.ixl;
  941.     sna.iyh=vga.iyh;
  942.     sna.iyl=vga.iyl;
  943.  
  944.     sna.border=vga.border; 
  945.  
  946.     sna.i=vga.i;
  947.     sna.r=vga.r;
  948.  
  949.     /* If register I has changed, chances are good that it runs in
  950.        IM2 mode */
  951.     if(sna.i==0x3f)
  952.         sna.im=0x01; 
  953.     else
  954.         sna.im=0x02; 
  955.         
  956.     if((vga.im & 0x01) == 0)
  957.         sna.iff2=0x00;
  958.     else
  959.         sna.iff2=0xff;
  960.  
  961.     sp=256*vga.sph+vga.spl;
  962.     sp=sp-2;
  963.     addr=sp-0x4000;
  964.     image[addr]=vga.pcl;
  965.     image[addr+1]=vga.pch;
  966.         
  967.     sna.sph=sp/256;
  968.     sna.spl=sp%256;
  969. }
  970.  
  971. void raw_to_sna()
  972. {
  973.     unsigned int addr;
  974.     unsigned int sp;
  975.     unsigned int pc;
  976.  
  977.     pc=0x1bf4; /* entry of "next statement" */
  978.  
  979.     sna.f=0x99;
  980.     sna.a=0x5f;
  981.     sna.b=0x1f;
  982.     sna.c=0xf0;
  983.     sna.d=0x5d;
  984.     sna.e=0x0c;
  985.     sna.h=0x5d;
  986.     sna.l=0x0e;
  987.  
  988.     sna.fax=0x44;
  989.     sna.aax=0x00;
  990.     sna.bax=0x18;
  991.     sna.cax=0x20;
  992.     sna.dax=0x00;
  993.     sna.eax=0x07;
  994.     sna.hax=0x5c;
  995.     sna.lax=0xf1;
  996.  
  997.     sna.ixh=0x03;
  998.     sna.ixl=0xd4;
  999.     sna.iyh=0x5c;
  1000.     sna.iyl=0x3a;
  1001.  
  1002.     sna.i=0x3f;
  1003.     sna.r=0x00;
  1004.     sna.im=0x01;
  1005.     sna.iff2=0xFF;
  1006.  
  1007.     /* set sp by means of RAMTOP in the image */
  1008.     addr=0x5cb2-0x4000;
  1009.     sp=256*image[addr+1]+image[addr]-1;
  1010.  
  1011.     /* Reset ERR NR to no error */
  1012.     image[0x5c3a-0x4000]=0xff;
  1013.     
  1014.     /* Set border by means of BORDCR */
  1015.     sna.border=(image[0x5c48-0x4000] & 0x38)>>3;
  1016.     
  1017.     /* put return address to MAIN-4 (0x1303) on stack */
  1018.     sp=sp-2;
  1019.     addr=sp-0x4000;    
  1020.     image[addr]=0x03; 
  1021.     image[addr+1]=0x13;
  1022.     
  1023.     sp=sp-2;
  1024.     addr=sp-0x4000;
  1025.     image[addr]=pc%256;
  1026.     image[addr+1]=pc/256;
  1027.  
  1028.     sna.sph=sp/256;
  1029.     sna.spl=sp%256;
  1030. }
  1031.  
  1032. void z80_to_sna()
  1033. {
  1034.     unsigned int addr;
  1035.     unsigned int sp;
  1036.  
  1037.     sna.f=z80.f;
  1038.     sna.a=z80.a;
  1039.     sna.b=z80.b;
  1040.     sna.c=z80.c;
  1041.     sna.d=z80.d;
  1042.     sna.e=z80.e;
  1043.     sna.h=z80.h;
  1044.     sna.l=z80.l;
  1045.  
  1046.     sna.fax=z80.fax;
  1047.     sna.aax=z80.aax;
  1048.     sna.bax=z80.bax;
  1049.     sna.cax=z80.cax;
  1050.     sna.dax=z80.dax;
  1051.     sna.eax=z80.eax;
  1052.     sna.hax=z80.hax;
  1053.     sna.lax=z80.lax;
  1054.  
  1055.     sna.ixh=z80.ixh;
  1056.     sna.ixl=z80.ixl;
  1057.     sna.iyh=z80.iyh;
  1058.     sna.iyl=z80.iyl;
  1059.  
  1060.     sna.border=(z80.data/2) & 0x07; 
  1061.  
  1062.     sna.i=z80.i;
  1063.  
  1064.     if(z80.data==0xff) z80.data=0;
  1065.  
  1066.     if((z80.data & 0x01)==1)
  1067.         sna.r=(z80.r & 0x7f)+0x80;
  1068.     else
  1069.         sna.r=z80.r & 0x7f;
  1070.  
  1071.     sna.im=z80.im & 0x03;
  1072.     
  1073.     if(z80.iff2 != 0)
  1074.         sna.iff2=0xff;
  1075.     else
  1076.         sna.iff2=0x00;
  1077.  
  1078.     sp=256*z80.sph+z80.spl;
  1079.     sp=sp-2;
  1080.     addr=sp-0x4000;
  1081.         
  1082.     sna.sph=sp/256;
  1083.     sna.spl=sp%256;
  1084.  
  1085.     image[addr]=z80.pcl;
  1086.     image[addr+1]=z80.pch;
  1087. }
  1088.  
  1089. void prg_to_sna()
  1090. {
  1091.     unsigned int addr;
  1092.     unsigned int sp;
  1093.  
  1094.     sna.b=prg.b;
  1095.     sna.c=prg.c;
  1096.     sna.d=prg.d;
  1097.     sna.e=prg.e;
  1098.     sna.h=prg.h;
  1099.     sna.l=prg.l;
  1100.     sna.fax=prg.fax;
  1101.     sna.aax=prg.aax;
  1102.     sna.bax=prg.bax;
  1103.     sna.cax=prg.cax;
  1104.     sna.dax=prg.dax;
  1105.     sna.eax=prg.eax;
  1106.     sna.hax=prg.hax;
  1107.     sna.lax=prg.lax;
  1108.  
  1109.     sna.ixh=prg.ixh;
  1110.     sna.ixl=prg.ixl;
  1111.     sna.iyh=prg.iyh;
  1112.     sna.iyl=prg.iyl;
  1113.  
  1114.     /* Set border by means of BORDCR */
  1115.     sna.border=(image[0x5c48-0x4000] & 0x38)>>3;
  1116.  
  1117.     sna.i=prg.i;
  1118.  
  1119.     if(prg.i==0x3f)
  1120.         sna.im=0x01;
  1121.     else
  1122.         sna.im=0x02;
  1123.  
  1124.     sp=256*prg.sph+prg.spl;
  1125.     sp=sp+4; /* there are two more words on the stack besides PC */
  1126.     addr=sp-0x4000;
  1127.  
  1128.     sna.r=image[addr-3];
  1129.     /* the af combo is on the stack */
  1130.     sna.f=image[addr-2];
  1131.     sna.a=image[addr-1];
  1132.         
  1133.     sna.sph=sp/256;
  1134.     sna.spl=sp%256;
  1135.  
  1136.     /* interrupts always on ??? */
  1137.     sna.iff2=prg.iff2;
  1138. }
  1139.  
  1140. void ach_to_sna()
  1141. {
  1142.     unsigned int addr;
  1143.     unsigned int sp;
  1144.  
  1145.     sna.f=ach.f;
  1146.     sna.a=ach.a;
  1147.     sna.b=ach.b;
  1148.     sna.c=ach.c;
  1149.     sna.d=ach.d;
  1150.     sna.e=ach.e;
  1151.     sna.h=ach.h;
  1152.     sna.l=ach.l;
  1153.  
  1154.     sna.fax=ach.fax;
  1155.     sna.aax=ach.aax;
  1156.     sna.bax=ach.bax;
  1157.     sna.cax=ach.cax;
  1158.     sna.dax=ach.dax;
  1159.     sna.eax=ach.eax;
  1160.     sna.hax=ach.hax;
  1161.     sna.lax=ach.lax;
  1162.  
  1163.     sna.ixh=ach.ixh;
  1164.     sna.ixl=ach.ixl;
  1165.     sna.iyh=ach.iyh;
  1166.     sna.iyl=ach.iyl;
  1167.  
  1168.     sna.border=ach.border;
  1169.  
  1170.     sna.i=ach.i;
  1171.  
  1172.     sna.r=ach.r;
  1173.  
  1174.     sna.im=ach.im & 0x02; 
  1175.         
  1176.     sna.iff2=ach.iff2;
  1177.  
  1178.     sp=256*ach.sph+ach.spl;
  1179.     sp=sp-2;
  1180.     addr=sp-0x4000;
  1181.         
  1182.     sna.sph=sp/256;
  1183.     sna.spl=sp%256;
  1184.  
  1185.     image[addr]=ach.pcl;
  1186.     image[addr+1]=ach.pch;
  1187. }
  1188.  
  1189. void kgb_to_sna()
  1190. {
  1191.     unsigned int addr;
  1192.     unsigned int sp;
  1193.  
  1194.     sna.f=kgb.f;
  1195.     sna.a=kgb.a;
  1196.     sna.b=kgb.b;
  1197.     sna.c=kgb.c;
  1198.     sna.d=kgb.d;
  1199.     sna.e=kgb.e;
  1200.     sna.h=kgb.h;
  1201.     sna.l=kgb.l;
  1202.  
  1203.     sna.fax=kgb.fax;
  1204.     sna.aax=kgb.aax;
  1205.     sna.bax=kgb.bax;
  1206.     sna.cax=kgb.cax;
  1207.     sna.dax=kgb.dax;
  1208.     sna.eax=kgb.eax;
  1209.     sna.hax=kgb.hax;
  1210.     sna.lax=kgb.lax;
  1211.  
  1212.     sna.ixh=kgb.ixh;
  1213.     sna.ixl=kgb.ixl;
  1214.     sna.iyh=kgb.iyh;
  1215.     sna.iyl=kgb.iyl;
  1216.  
  1217.     sna.i=kgb.i;
  1218.     sna.r=kgb.r;
  1219.  
  1220.     /* border-colour not found in KGB image */
  1221.     /* Set border by means of BORDCR */
  1222.     sna.border=(image[0x5c48-0x4000] & 0x38)>>3;
  1223.  
  1224.     /* determine interrupt mode using the value of register I */
  1225.     if (kgb.intmode_l==0xff)
  1226.         sna.im=0x00; 
  1227.     else if(kgb.intmode_l==1)
  1228.         sna.im=0x02; 
  1229.     else
  1230.         sna.im=0x01;
  1231.         
  1232.     if((kgb.interruptstatus & 0x01) != 0)
  1233.         sna.iff2=0xff;
  1234.     else
  1235.         sna.iff2=0x0;
  1236.  
  1237.     sp=256*kgb.sph+kgb.spl;
  1238.     sp=sp-2;
  1239.     addr=sp-0x4000;
  1240.         
  1241.     sna.sph=sp/256;
  1242.     sna.spl=sp%256;
  1243.  
  1244.     image[addr]=kgb.pcl;
  1245.     image[addr+1]=kgb.pch;
  1246. }
  1247.  
  1248. /* CONVERSION FUNCTIONS - FROM .SNA FORMAT */
  1249.  
  1250. void sna_to_vgaspec()
  1251. {
  1252.     unsigned int addr;
  1253.     unsigned int sp;
  1254.     unsigned int pc;
  1255.  
  1256.     sp=256*sna.sph+sna.spl;
  1257.     addr=sp-0x4000;
  1258.     pc=image[addr]+256*image[addr+1];
  1259.     sp=sp+2;
  1260.  
  1261.     vga.S='S';
  1262.     vga.P='P';
  1263.     vga.len_l=0x00;
  1264.     vga.len_h=0xC0;
  1265.     vga.start_l=0x00;
  1266.     vga.start_h=0x40;
  1267.     vga.f=sna.f;
  1268.     vga.a=sna.a;
  1269.     vga.b=sna.b;
  1270.     vga.c=sna.c;
  1271.     vga.d=sna.d;
  1272.     vga.e=sna.e;
  1273.     vga.h=sna.h;
  1274.     vga.l=sna.l;
  1275.  
  1276.     vga.fax=sna.fax;
  1277.     vga.aax=sna.aax;
  1278.     vga.bax=sna.bax;
  1279.     vga.cax=sna.cax;
  1280.     vga.dax=sna.dax;
  1281.     vga.eax=sna.eax;
  1282.     vga.hax=sna.hax;
  1283.     vga.lax=sna.lax;
  1284.  
  1285.     vga.ixh=sna.ixh;
  1286.     vga.ixl=sna.ixl;
  1287.     vga.iyh=sna.iyh;
  1288.     vga.iyl=sna.iyl;
  1289.  
  1290.     vga.i=sna.i;
  1291.     vga.r=sna.r;
  1292.  
  1293.     vga.im=sna.im & 0x02; /* 0 for IM1, 2 for IM2 */
  1294.  
  1295.     /* works? how does it know it was IM1 ? */
  1296.     if((sna.iff2 & 0x04) != 0)
  1297.         vga.im=vga.im | 0x01; 
  1298.  
  1299.     vga.sph=sp/256;
  1300.     vga.spl=sp%256;
  1301.     
  1302.     vga.pch=pc/256;
  1303.     vga.pcl=pc%256;
  1304.  
  1305.     vga.border=sna.border; 
  1306.  
  1307.     vga.res2=0;
  1308.     vga.res3=0;
  1309.     vga.res4=0;
  1310.     vga.res5=0;
  1311. }
  1312.  
  1313. void sna_to_z80()
  1314. {
  1315.     unsigned int addr;
  1316.     unsigned int sp;
  1317.     unsigned int pc;
  1318.  
  1319.     sp=256*sna.sph+sna.spl;
  1320.     addr=sp-0x4000;
  1321.     pc=image[addr]+256*image[addr+1];
  1322.     sp=sp+2;
  1323.  
  1324.     z80.f=sna.f;
  1325.     z80.a=sna.a;
  1326.     z80.b=sna.b;
  1327.     z80.c=sna.c;
  1328.     z80.d=sna.d;
  1329.     z80.e=sna.e;
  1330.     z80.h=sna.h;
  1331.     z80.l=sna.l;
  1332.  
  1333.     z80.fax=sna.fax;
  1334.     z80.aax=sna.aax;
  1335.     z80.bax=sna.bax;
  1336.     z80.cax=sna.cax;
  1337.     z80.dax=sna.dax;
  1338.     z80.eax=sna.eax;
  1339.     z80.hax=sna.hax;
  1340.     z80.lax=sna.lax;
  1341.  
  1342.     z80.ixh=sna.ixh;
  1343.     z80.ixl=sna.ixl;
  1344.     z80.iyh=sna.iyh;
  1345.     z80.iyl=sna.iyl;
  1346.  
  1347.     z80.i=sna.i;
  1348.     z80.r=sna.r | 0x080; /* bit 7 is stored somewhere else, always set */
  1349.     z80.im=sna.im & 0x03;
  1350.     z80.im=z80.im + 0x60; /* fixed normal video/kempston joystick */
  1351.  
  1352.     z80.sph=sp/256;
  1353.     z80.spl=sp%256;
  1354.     
  1355.     z80.pch=pc/256;
  1356.     z80.pcl=pc%256;
  1357.  
  1358.     /* all kinds of stuff put in "data" */
  1359.     z80.data=(sna.border & 0x07)*2; 
  1360.     if((sna.r & 0x80)!=0) z80.data=z80.data+1; /* here is bit 7 of r */
  1361.  
  1362.     /* image is not compressed, compression will be done by the */
  1363.     /* z80_write function.                                      */
  1364.     z80.data = z80.data & ~0x20; /* reset compressed mode bit to be sure */
  1365.  
  1366.     if((sna.iff2 & 0x04) != 0) {
  1367.         z80.iff1=0xff;
  1368.         z80.iff2=0xff;
  1369.     } else {
  1370.         z80.iff1=0;
  1371.         z80.iff2=0;
  1372.     }
  1373. }
  1374.  
  1375. void sna_to_prg(char * n)
  1376. {
  1377.     unsigned int addr;
  1378.     unsigned int sp;
  1379.     int i;
  1380.     unsigned char * p;
  1381.  
  1382.     /* clean header structure first */
  1383.     p=(unsigned char *) &prg;
  1384.     for(i=0; i < 256; i++)
  1385.         p[i]='\0';
  1386.  
  1387.     prg.contains_0x61=0x61; /* size of image in sectors */
  1388.     prg.contains_0x35=0x35; /* don't know yet */
  1389.     prg.contains_0x03=0x03; /* don't know yet */
  1390.  
  1391.     sp=256*sna.sph+sna.spl;
  1392.     addr=sp-0x4000;
  1393.  
  1394.     /* these are on the stack */
  1395.     image[addr-1]=sna.a;
  1396.     image[addr-2]=sna.f;
  1397.     image[addr-3]=sna.r;
  1398.     image[addr-4]=sna.iff2;
  1399.  
  1400.     sp=sp-4;
  1401.  
  1402.     prg.name[0]='\0';
  1403.     strncpy(prg.name,n,10);
  1404.     prg.name[10]='\0';
  1405.  
  1406.     prg.b=sna.b;
  1407.     prg.c=sna.c;
  1408.     prg.d=sna.d;
  1409.     prg.e=sna.e;
  1410.     prg.h=sna.h;
  1411.     prg.l=sna.l;
  1412.  
  1413.     prg.fax=sna.fax;
  1414.     prg.aax=sna.aax;
  1415.     prg.bax=sna.bax;
  1416.     prg.cax=sna.cax;
  1417.     prg.dax=sna.dax;
  1418.     prg.eax=sna.eax;
  1419.     prg.hax=sna.hax;
  1420.     prg.lax=sna.lax;
  1421.  
  1422.     prg.ixh=sna.ixh;
  1423.     prg.ixl=sna.ixl;
  1424.     prg.iyh=sna.iyh;
  1425.     prg.iyl=sna.iyl;
  1426.  
  1427.     prg.i=sna.i;
  1428.     prg.iff2=sna.iff2;
  1429.  
  1430.     prg.sph=sp/256;
  1431.     prg.spl=sp%256;
  1432.     
  1433.     /* prg.border=sna.border; */
  1434. }
  1435.  
  1436. void sna_to_ach()
  1437. {
  1438.     unsigned int addr;
  1439.     unsigned int sp;
  1440.     unsigned int pc;
  1441.     int i;
  1442.     unsigned char * p;
  1443.  
  1444.     /* clean header structure first */
  1445.     p=(unsigned char *) &ach;
  1446.     for(i=0; i < 256; i++)
  1447.         p[i]='\0';
  1448.  
  1449.     sp=256*sna.sph+sna.spl;
  1450.     addr=sp-0x4000;
  1451.     pc=image[addr]+256*image[addr+1];
  1452.     sp=sp+2;
  1453.  
  1454.     ach.f=sna.f;
  1455.     ach.a=sna.a;
  1456.     ach.b=sna.b;
  1457.     ach.c=sna.c;
  1458.     ach.d=sna.d;
  1459.     ach.e=sna.e;
  1460.     ach.h=sna.h;
  1461.     ach.l=sna.l;
  1462.  
  1463.     ach.fax=sna.fax;
  1464.     ach.aax=sna.aax;
  1465.     ach.bax=sna.bax;
  1466.     ach.cax=sna.cax;
  1467.     ach.dax=sna.dax;
  1468.     ach.eax=sna.eax;
  1469.     ach.hax=sna.hax;
  1470.     ach.lax=sna.lax;
  1471.  
  1472.     ach.ixh=sna.ixh;
  1473.     ach.ixl=sna.ixl;
  1474.     ach.iyh=sna.iyh;
  1475.     ach.iyl=sna.iyl;
  1476.  
  1477.     ach.i=sna.i;
  1478.     ach.r=sna.r;
  1479.  
  1480.     ach.border=sna.border;
  1481.  
  1482.     if((sna.iff2 & 0x04) != 0)
  1483.         ach.iff2=0xff;
  1484.     else
  1485.         ach.iff2=0x00;
  1486.  
  1487.     ach.sph=sp/256;
  1488.     ach.spl=sp%256;
  1489.     
  1490.     ach.pch=pc/256;
  1491.     ach.pcl=pc%256;
  1492. }
  1493.  
  1494. void sna_to_kgb()
  1495. {
  1496.     unsigned int addr;
  1497.     unsigned int sp;
  1498.     unsigned int pc;
  1499.     int i;
  1500.     unsigned char * p;
  1501.  
  1502.     /* clean info structure first */
  1503.     p = (unsigned char *) &kgb;
  1504.     for(i=0; i < 202; i++)
  1505.         p[i]='\0';
  1506.  
  1507.     /* make some assumptions here */
  1508.     kgb.is3_1 = 3;        /* always 3, don't ask me why */
  1509.     kgb.colourmode = 1;    /* assume colour */
  1510.     kgb.soundmode = 1;    /* assume simple sound */
  1511.     kgb.haltmode = 1;    /* assume not in halt mode */
  1512.  
  1513.     sp=256*sna.sph+sna.spl;
  1514.     addr=sp-0x4000;
  1515.     pc=image[addr]+256*image[addr+1];
  1516.     sp=sp+2;
  1517.  
  1518.     kgb.f=sna.f;
  1519.     kgb.a=sna.a;
  1520.     kgb.b=sna.b;
  1521.     kgb.c=sna.c;
  1522.     kgb.d=sna.d;
  1523.     kgb.e=sna.e;
  1524.     kgb.h=sna.h;
  1525.     kgb.l=sna.l;
  1526.  
  1527.     kgb.fax=sna.fax;
  1528.     kgb.aax=sna.aax;
  1529.     kgb.bax=sna.bax;
  1530.     kgb.cax=sna.cax;
  1531.     kgb.dax=sna.dax;
  1532.     kgb.eax=sna.eax;
  1533.     kgb.hax=sna.hax;
  1534.     kgb.lax=sna.lax;
  1535.  
  1536.     kgb.ixh=sna.ixh;
  1537.     kgb.ixl=sna.ixl;
  1538.     kgb.iyh=sna.iyh;
  1539.     kgb.iyl=sna.iyl;
  1540.  
  1541.     kgb.i=sna.i;
  1542.  
  1543.     kgb.r=sna.r;
  1544.  
  1545.     /* kgb.border=sna.border; NOT IN KGB IMAGE! */
  1546.  
  1547.     /* Interupt mode is stored in a word in the KGB format. */
  1548.     /* Use byte accesses to be CPU independent              */
  1549.  
  1550.     switch (sna.im & 0x03) {
  1551.     case 0:    kgb.intmode_h = 0xff;
  1552.         kgb.intmode_l = 0xff;
  1553.         break;
  1554.     case 2: kgb.intmode_h = 0;
  1555.         kgb.intmode_l = 1;
  1556.         break;
  1557.     default:kgb.intmode_h = 0;
  1558.         kgb.intmode_l = 0;
  1559.         break;
  1560.     }
  1561.  
  1562.     if((sna.iff2 & 0x04) != 0)
  1563.         kgb.interruptstatus=0x01;
  1564.     else
  1565.         kgb.interruptstatus=0x00;
  1566.  
  1567.     kgb.sph=sp/256;
  1568.     kgb.spl=sp%256;
  1569.     
  1570.     kgb.pch=pc/256;
  1571.     kgb.pcl=pc%256;
  1572. }
  1573.  
  1574. /* 16K PAGE READ FUNCTION FOR .Z80 FORMAT */
  1575.  
  1576. int z80_read_page(char * s)
  1577. {
  1578.     struct    z80_page_s page_info;
  1579.     unsigned int    len;
  1580.     unsigned int    pos;
  1581.     long        f_len;
  1582.  
  1583.     if(fread(&page_info,sizeof(struct z80_page_s),1,fd)!=1)    {
  1584.         return 0;
  1585.     }
  1586.     len = (256 * page_info.blocklen_h) + page_info.blocklen_l;
  1587.  
  1588.     switch(page_info.page_num) {
  1589.     case 0:    fprintf(stderr,"%s - memory page 0 - 48K rom ignored\n",s);
  1590.         pos=0x0ffff;
  1591.         break;
  1592.     case 1:    fprintf(stderr,"%s - memory page 1 - Interface 1 rom ignored\n",s);
  1593.         pos=0x0ffff;
  1594.         break;
  1595.     case 2:    fprintf(stderr,"%s - memory page 2 - basic samram rom ignored\n",s);
  1596.         pos=0x0ffff;
  1597.         break;
  1598.     case 3:    fprintf(stderr,"%s - memory page 3 - monitor samram rom ignored\n",s);
  1599.         pos=0x0ffff;
  1600.         break;
  1601.     case 4:    pos=0x04000;    /* second 16K of RAM area */
  1602.         break;
  1603.     case 5:    pos=0x08000;    /* third 16K of RAM area */
  1604.         break;
  1605.     case 6:    fprintf(stderr,"%s - memory page 6 - shadow rom 8000-BFFF ignored\n",s);
  1606.         pos=0x0ffff;
  1607.         break;
  1608.     case 7:    fprintf(stderr,"%s - memory page 7 - shadow rom C000-FFFF ignored\n",s);
  1609.         pos=0x0ffff;
  1610.         break;
  1611.     case 8:    pos=0;        /* first 16K of RAM area */
  1612.         break;
  1613.     case 9:    fprintf(stderr,"%s - memory page 8 - 128K page 6 ignored\n",s);
  1614.         pos=0x0ffff;
  1615.         break;
  1616.     case 10:fprintf(stderr,"%s - memory page 10 - 128K page7 ignored\n",s);
  1617.         pos=0x0ffff;
  1618.         break;
  1619.     default:fprintf(stderr,"%s - memory page %d - Invalid page number -fatal-\n",s,page_info.page_num);
  1620.         exit(1);
  1621.         break;
  1622.     }
  1623.  
  1624.     if(pos == (unsigned int) 0x0ffff) {
  1625.         /* wrong page, seek over this page */
  1626.         if(fseek(fd,(long) len, SEEK_CUR)!=0) {
  1627.             perror(s);
  1628.             exit(1);
  1629.         }
  1630.     } else {
  1631.         /* Valid 48K page, read and uncompress */
  1632.  
  1633.         f_len = 0 - ftell(fd);
  1634.         z80_read_uncompress(fd,pos,16384);
  1635.         f_len = f_len + ftell(fd);
  1636.  
  1637.         if((long) len != f_len) {
  1638.             fprintf(stderr,"Z80 image corrupted, can't convert\n");
  1639.             exit(1);
  1640.         }
  1641.     }
  1642.     return 1;
  1643. }
  1644.  
  1645. /* COMPRESSION/DECOMPRESSION for .Z80 FORMAT */
  1646.  
  1647. void z80_read_uncompress(FILE * fd, unsigned int start, unsigned int imsize)
  1648. {
  1649.     int          c,j,k;
  1650.     unsigned char l;
  1651.     unsigned char im;
  1652.  
  1653.     j=start;
  1654.     while(j<(start+imsize)) {
  1655.         c=getc(fd);
  1656.         if(c == -1) return;
  1657.         im = (unsigned char) c;
  1658.  
  1659.         if(im!=0xed) {
  1660.             image[j++]=im;
  1661.         } else {
  1662.             c=getc(fd);
  1663.             if(c == -1) return;
  1664.             im = (unsigned char) c;
  1665.             if(im!=0xed) {
  1666.                 image[j++]=0xed;
  1667.                 ungetc(im,fd);
  1668.             } else {
  1669.                 /* fetch count */
  1670.                 k=getc(fd);
  1671.                 if(k == -1) return;
  1672.                 /* fetch character */
  1673.                 c=getc(fd);
  1674.                 if(c == -1) return;
  1675.                 l = (unsigned char) c;
  1676.                 while(k!=0) {
  1677.                     image[j++]=l;
  1678.                     k--;
  1679.                 }
  1680.             }
  1681.         }
  1682.     }
  1683.  
  1684.     if(j!=(start+imsize)) {
  1685.         fprintf(stderr,"Z80 image corrupted, can't decompress\n");
  1686.         exit(6);
  1687.     }
  1688. }
  1689.  
  1690. int z80_compress()
  1691. {
  1692. #ifdef __TURBOC__
  1693.     unsigned char far * comp;
  1694. #else
  1695.     unsigned char * comp;
  1696. #endif
  1697.     unsigned int i,j;
  1698.     unsigned int num;
  1699.     unsigned char c,n;
  1700.     unsigned int ed;
  1701.  
  1702.     z80_size=(unsigned int) IMSIZE;
  1703.  
  1704.     /*
  1705.      * We need an intermediate buffer here, if the compressed image
  1706.      * is bigger than the uncompressed image than the image will
  1707.      * not be compressed to save space (!)
  1708.      */
  1709.  
  1710. #ifdef __TURBOC__
  1711.     comp=farmalloc(IMSIZE+0x0100);
  1712. #else
  1713.     comp=malloc(IMSIZE+0x0100);
  1714. #endif
  1715.     if(comp==NULL)
  1716.     {
  1717.         printf("Warning: Not enough memory to compress the image, using uncopressed image\n");
  1718.         return NOTCOMPRESSED;
  1719.     }
  1720.  
  1721.     i=0;
  1722.     j=0;
  1723.     /* ensure 'ed' is not set */
  1724.     ed=NO;
  1725.     while(i<IMSIZE)
  1726.     {
  1727.         c=image[i];
  1728.         i++;
  1729.         if(i<IMSIZE)
  1730.         {
  1731.             n=image[i];
  1732.         }
  1733.         else
  1734.         {
  1735.             /* force 'n' to be unequal to 'c' */
  1736.             n=c;
  1737.             n++;
  1738.         }
  1739.  
  1740.         if(c!=n)
  1741.         {
  1742.             comp[j]=c;
  1743.             j++;
  1744.             if(c==0xed) 
  1745.                 ed=YES;
  1746.             else
  1747.                 ed=NO;
  1748.         }
  1749.         else
  1750.         {
  1751.             if(c==0xed)
  1752.             {
  1753.                 /* two times 0xed - special care */
  1754.                 comp[j]=0xed;
  1755.                 j++;
  1756.                 comp[j]=0xed;
  1757.                 j++;
  1758.                 comp[j]=0x02;
  1759.                 j++;
  1760.                 comp[j]=0xed;
  1761.                 j++;
  1762.                 i++; /* skip second ED */
  1763.  
  1764.                 /* because 0xed is valid compressed we don't
  1765.                    have to watch it! */
  1766.                 ed=NO;
  1767.             }
  1768.             else if(ed==YES)
  1769.             {
  1770.                 /* can't compress now, skip this double pair */
  1771.                 comp[j]=c;
  1772.                 j++;
  1773.                 ed=NO;    /* 'c' can't be 0xed */
  1774.             }
  1775.             else
  1776.             {
  1777.                 num=1;
  1778.                 while(i<IMSIZE)
  1779.                 {
  1780.                     if(c!=image[i])
  1781.                         break;
  1782.                     num++;
  1783.                     i++;
  1784.                     if(num==255)
  1785.                         break;
  1786.                 }
  1787.                 if(num <= 4)
  1788.                 {
  1789.                     /* no use to compress */
  1790.                     while(num!=0)
  1791.                     {
  1792.                         comp[j]=c;
  1793.                         j++;
  1794.                         num--;
  1795.                     }
  1796.                 }
  1797.                 else
  1798.                 {
  1799.                     comp[j]=0xed;
  1800.                     j++;
  1801.                     comp[j]=0xed;
  1802.                     j++;
  1803.                     comp[j]=(unsigned char) num;
  1804.                     j++;
  1805.                     comp[j]=c;
  1806.                     j++;
  1807.                 }
  1808.             }
  1809.         }
  1810.  
  1811.         if(j >= (IMSIZE-4))
  1812.         {
  1813.             /* compressed image bigger or same than original */
  1814. #ifdef __TURBOC__
  1815.             farfree(comp);
  1816. #else
  1817.             free(comp);
  1818. #endif
  1819.             return NOTCOMPRESSED;
  1820.         }
  1821.     }
  1822.     /* append "end of compressed area" mark */
  1823.     comp[j]=0;
  1824.     j++;
  1825.     comp[j]=0xed;
  1826.     j++;
  1827.     comp[j]=0xed;
  1828.     j++;
  1829.     comp[j]=0;
  1830.     j++;
  1831.  
  1832.     z80_size = j;
  1833.     
  1834.     /* copy back */
  1835.     i=0;
  1836.     j=0;
  1837.     while(i<IMSIZE)
  1838.         image[i++]=comp[j++];
  1839. #ifdef __TURBOC__
  1840.     farfree(comp);
  1841. #else
  1842.     free(comp);
  1843. #endif
  1844.  
  1845.     return COMPRESSED;
  1846. }
  1847.